﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using Microsoft.Scripting.Runtime;
using Microsoft.Scripting;
using Antlr.Runtime;
using Antlr.Runtime.Tree;
using Microsoft.Scripting.Interpretation;
using JavascriptEngine.Compiler;
using Microsoft.Scripting.Ast;

namespace JavascriptEngine.Runtime
{
    public class JavascriptContext : LanguageContext
    {
        internal const string JavascriptDisplayName = "Javascript";
        internal const string JavascriptNames = "Javascript;js";
        internal const string JavascriptFileExtensions = ".js";

        public JavascriptContext(ScriptDomainManager manager, IDictionary<string, object> options)
            : base(manager)
        {
        }

        protected override ScriptCode CompileSourceCode(SourceUnit sourceUnit, CompilerOptions options, ErrorSink errorSink)
        {
            CompilerContext context = new CompilerContext(sourceUnit, options, errorSink);

            return ParseAndBuildAst(context);
        }

        private ScriptCode ParseAndBuildAst(CompilerContext context)
        {
            if (!context.SourceUnit.HasPath)
                throw new NotImplementedException("You must pass a file to the compiler.");
            Antlr.Runtime.ANTLRFileStream fs = new ANTLRFileStream(context.SourceUnit.Path); // @"C:\Users\HaythamAlaa\Documents\Downloads\benchmarks-v1\crypto.js"
            ECMAScriptLexer lexer = new ECMAScriptLexer(fs);
            ITokenSource source = (ITokenSource)lexer;
            Antlr.Runtime.CommonTokenStream tokens = new CommonTokenStream();
            tokens.TokenSource = lexer;
            ECMAScriptParser parser = new ECMAScriptParser(tokens);
            CommonTree ast = parser.program().Tree as CommonTree;

            return TransformAndBindAst(context, ast);
        }

        private ScriptCode TransformAndBindAst(CompilerContext context, CommonTree ast)
        {
            AstGenerator ag = new AstGenerator(context, ast);
            
            // DLR:3498, http://dlr.codeplex.com/WorkItem/View.aspx?WorkItemId=3498
            // is blocking us from using InterpretedScriptCode
            return new InterpretedScriptCode(ag.SubGenerate(), context.SourceUnit);            
            //return new LegacyScriptCode(ag.SubGenerate(),  context.SourceUnit);
        }
    }
}
